package com.example.book_system.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.book_system.common.Methods;
import com.example.book_system.common.Result;
import com.example.book_system.config.BookConfig;
import com.example.book_system.entity.Book;
import com.example.book_system.entity.ReadHistory;
import com.example.book_system.entity.Reader;
import com.example.book_system.mapper.BookMapper;
import com.example.book_system.mapper.ReadHistoryMapper;
import com.example.book_system.mapper.ReaderMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
 * 实现几个接口
 * 1. 借书
 * 2. 还书
 * 3. 查询借还记录
 * 4. 当前借阅
 * @author BlueRose
 */
@Service("readerService")
public class ReaderServiceImpl implements IReaderService{
    private final BookMapper bookMapper;
    private final ReadHistoryMapper readHistoryMapper;
    private final ReaderMapper readerMapper;
    @Autowired
    ReaderServiceImpl(BookMapper bookMapper, ReadHistoryMapper readHistoryMapper, ReaderMapper readerMapper){
        this.bookMapper = bookMapper;
        this.readHistoryMapper = readHistoryMapper;
        this.readerMapper = readerMapper;
    }

    private Book getBookByIsbn(String isbn){
        QueryWrapper<Book> wrapper = new QueryWrapper<>();
        wrapper.eq("isbn", isbn);
        return bookMapper.selectOne(wrapper);
    }

    @Override
    public Result<String> borrowBook(Map<String, String> params) {
        String isbn = params.get("isbn");
        String id = params.get("id");
        if(id == null || isbn == null){
            return new Result<>(Result.FAILED_CODE, "ISBN和ID不能为空!", "failed");
        }
        QueryWrapper<Reader> readerQueryWrapper = new QueryWrapper<>();
        readerQueryWrapper.eq("id", new Integer(id));
        Reader reader = readerMapper.selectOne(readerQueryWrapper);
        if(reader == null){
            return new Result<>(Result.FAILED_CODE, "系统中没有该读者", "failed");
        }
        Book book = getBookByIsbn(isbn);
        if(book == null){
            return new Result<>(Result.FAILED_CODE, "该isbn无效或该书不存在馆内", "failed");
        }else{
            if(book.getTotal() <= book.getBorrow()){
                return new Result<>(Result.FAILED_CODE, "该书被借完", "failed");
            }else{
                // 先判断自己有没有借这本书
                QueryWrapper<ReadHistory> wrapper = new QueryWrapper<>();
                wrapper.eq("id", id);
                wrapper.eq("returned", BookConfig.NOT_RETURNED).or().eq("returned", null);
                int length = 0;
                List<ReadHistory> readHistoryList = readHistoryMapper.selectList(wrapper);
                if(readHistoryList != null){
                    for (ReadHistory readHistory : readHistoryList) {
                        if(isbn.equals(readHistory.getIsbn())){
                            return new Result<>(Result.FAILED_CODE, "你已经借过该书了", "failed");
                        }
                        ++length;
                    }
                }
                // 再判断自己有没有达到借书上限
                // 由于之前是已经把所有没还的书都查了 所以不用再查库了
                // 且之前会遍历 就可以在遍历的同时拿到长度 因为如果说没有遍历完 说明返回了 也走不到这一步
                if(readHistoryList != null){
                    if(length >= reader.getMax()){
                        return new Result<>(Result.FAILED_CODE, "超出借书上限", "failed");
                    }
                }
                ReadHistory newHistory = new ReadHistory(id, isbn, Methods.getTimeNow(), book.getMax(), book.getName());
                book.setBorrow(book.getBorrow() + 1);
                bookMapper.update(book, new QueryWrapper<Book>().eq("isbn", isbn));
                readHistoryMapper.insert(newHistory);
                return new Result<>(Result.SUCCESS_CODE, "借阅成功", "success");
            }
        }
    }

    @Override
    public Result<String> returnBook(Map<String, String> params){
        String isbn = params.get("isbn");
        String id = params.get("id");
        Book book = getBookByIsbn(isbn);
        if(book == null){
            return new Result<>(Result.FAILED_CODE, "该isbn无效或该书不存在馆内", "failed");
        }else{
            if(book.getBorrow() <= 0){
                return new Result<>(Result.FAILED_CODE, "该书被还完", "failed");
                // todo 出现异常
            }else{
                // 有可能出现一个人借了该书两次的情况(只用isbn和id去确定的话 但是加入begin则可以唯一确定 否则就是出错)
                QueryWrapper<ReadHistory> wrapper = new QueryWrapper<>();
                wrapper.eq("id", id);
                wrapper.eq("isbn", isbn);
                List<ReadHistory> readHistoryList = readHistoryMapper.selectList(wrapper);
                if(readHistoryList != null){
                    for (ReadHistory readHistory : readHistoryList) {
                        if(BookConfig.NOT_RETURNED.equals(readHistory.getReturned())){
                            readHistory.setReturned(BookConfig.RETURNED);
                            readHistory.setEnd(Methods.getTimeNow());

                            // 计算罚款 2022-05-06
                            long distance = Methods.getCmTime(readHistory.getEnd()) - Methods.getCmTime(readHistory.getBegin());
                            System.out.println(Methods.getCmTime(readHistory.getEnd()));
                            System.out.println(Methods.getCmTime(readHistory.getBegin()));
                            if(distance > readHistory.getMax() * BookConfig.DAY_SPLIT){
                                double punish = (distance * BookConfig.PUNISH_DAY) / BookConfig.DAY_SPLIT;
                                readHistory.setPunish(punish);
                            }else{
                                readHistory.setPunish(0);
                            }
                            book.setBorrow(book.getBorrow() - 1);
                            bookMapper.update(book, new QueryWrapper<Book>().eq("isbn", isbn));
                            readHistoryMapper.update(readHistory, wrapper.eq("begin", readHistory.getBegin()));
                            return new Result<>(Result.SUCCESS_CODE, "还书成功", "success");
                        }
                    }
                }
                return new Result<>(Result.FAILED_CODE, "你没有借这本书", "failed");
            }
        }
    }

    @Override
    public Result<List<Book>> findBook(int currentPage, int pageSize, String name){
        IPage<Book> tmp = bookMapper.selectBookByPage(new Page<>(currentPage, pageSize), "%" + name + "%");
        List<Book> result = tmp.getRecords();
        return new Result<>(Result.SUCCESS_CODE, "" + tmp.getTotal(), result);
    }

    @Override
    public Result<List<ReadHistory>> getReadHistory(Map<String, String> params) {
        String id = params.get(BookConfig.ID);
        QueryWrapper<ReadHistory> wrapper = new QueryWrapper<>();
        wrapper.eq(BookConfig.ID, id);
        List<ReadHistory> result = readHistoryMapper.selectList(wrapper);
        return new Result<>(Result.SUCCESS_CODE, "请求成功", result);
    }

    @Override
    public Result<Reader> someReader(int id) {
        QueryWrapper<Reader> wrapper = new QueryWrapper<>();
        wrapper.select("name", "phone", "account", "id", "max", "identity");
        wrapper.eq("id", id);
        return new Result<>(Result.SUCCESS_CODE, "请求成功", readerMapper.selectOne(wrapper));
    }

    @Override
    public Result<String> changeReader(Reader reader) {
        if(reader.getId() < 0) {
            return new Result<>(Result.FAILED_CODE, "该用户不存在", "failed");
        }
        UpdateWrapper<Reader> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("name", reader.getName());
        updateWrapper.set("phone", reader.getPhone());
        updateWrapper.eq("id", reader.getId());
        try{
            readerMapper.update(reader, updateWrapper);
            return new Result<>(Result.SUCCESS_CODE, "修改成功", "success");
        }catch (NullPointerException e){
            e.printStackTrace();
            return new Result<>(Result.FAILED_CODE, "该用户不存在", "failed");
        }
    }

    @Override
    public Result<String> changePassword(int id, String oldPassword, String newPassword){
        if(id < 0){
            return new Result<>(Result.FAILED_CODE, "该用户不存在", "failed");
        }
        if(oldPassword == null || newPassword == null){
            return new Result<>(Result.FAILED_CODE, "新旧密码不能为空", "failed");
        }
        QueryWrapper<Reader> wrapper = new QueryWrapper<>();
        wrapper.eq("id", id);
        Reader reader = readerMapper.selectOne(wrapper);
        if(reader == null){
            return new Result<>(Result.FAILED_CODE, "该用户不存在", "failed");
        }
        if(!oldPassword.equals(reader.getPassword())){
            return new Result<>(Result.FAILED_CODE, "旧密码错误", "failed");
        }
        reader.setPassword(newPassword);
        UpdateWrapper<Reader> updateWrapper = new UpdateWrapper<>();
        updateWrapper.set("password", reader.getPassword());
        updateWrapper.eq("id", reader.getId());
        try{
            readerMapper.update(reader, updateWrapper);
            return new Result<>(Result.SUCCESS_CODE, "修改成功", "success");
        }catch(Exception e){
            return new Result<>(Result.FAILED_CODE, "修改步骤出错", "failed");
        }
    }

    public Result<String> login(String account, String password) {
        if(account == null || password == null){
            return new Result<>(Result.FAILED_CODE, "账号或密码为空", "failed");
        }else{
            QueryWrapper<Reader> wrapper = new QueryWrapper<>();
            wrapper.eq("account", account);
            Reader reader = readerMapper.selectOne(wrapper);
            if(reader == null) {
                return new Result<>(Result.FAILED_CODE, "账号不存在", "failed");
            }else{
                if(!password.equals(reader.getPassword())){
                    return new Result<>(Result.FAILED_CODE, "账号或密码错误", "failed");
                }else{
                    return new Result<>(Result.SUCCESS_CODE, "登录成功", String.valueOf(reader.getId()));
                }
            }
        }
    }
    @Override
    public Result<String> register(String account, String password, String name){
        if(account == null || password == null){
            return new Result<>(Result.FAILED_CODE, "账号或密码为空", "failed");
        }else{
            QueryWrapper<Reader> wrapper = new QueryWrapper<>();
            wrapper.eq("account", account);
            Reader reader = readerMapper.selectOne(wrapper);
            if(reader != null){
                return new Result<>(Result.FAILED_CODE, "该账号已存在", "failed");
            }else{
                if(name == null){
                    return new Result<>(Result.FAILED_CODE, "昵称为空", "failed");
                }else{
                    // 初始电话号码设为空 初始最大借阅上限为2 初始身份为普通读者
                    String phone = "";
                    int max = 2;
                    String identity = "0";
                    reader = new Reader(name, account, password, phone, max, identity);
                    readerMapper.insert(reader);
                    // 获取id发送 因为id不是后端生成的 是MySql自增生成的
                    // 而想做到用户注册即可登录就要获取 有些网站不支持注册即自动登录 就是因为不想获取返回 因为要查库
                    reader = readerMapper.selectOne(wrapper);
                    return new Result<>(Result.SUCCESS_CODE, "注册成功", String.valueOf(reader.getId()));
                }
            }
        }
    }
}
